package com.alei.redis.redisdemo.controller;

import com.alei.redis.redisdemo.bean.User;
import com.alibaba.fastjson.JSON;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;

/**
 * @author ShiLei
 * @version v1.0
 * @date 2020-06-27 17:26
 * <p>
 * Redis 字符串 string 数据类型使用场景
 */
@RestController
public class RedisStringDemoController {

    /**
     * 注入 redis 客户端连接池
     */
    @Resource
    private JedisPool jedisPool;

    /**
     * 计数器的简单实现演示 利用redis incr + decr的原子性操作简单实现
     */
    @RequestMapping("testStringIncrDecr")
    public Object testStringIncrDecr() {
        Jedis jedis = null;
        try {
            //1.从连接池获取jedis对象
            jedis = jedisPool.getResource();
            //2.执行操作 设置某一个计数值key
            jedis.set("user", "1");

            String count = jedis.get("user");
            System.out.println("最初 user 值为：" + count);
            for (int i = 0; i <= 10; i++) {
                jedis.incr("user");
            }

            String count1 = jedis.get("user");
            System.out.println("自增十次后 user 值为：" + count1);
            for (int i = 0; i <= 5; i++) {
                jedis.decr("user");
            }

            String count2 = jedis.get("user");
            System.out.println("自减五次后 user 值为：" + count2);
            return jedis.get("user");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != jedis) {
                jedis.close();
            }
        }
        return null;
    }

    /**
     * 演示分布式锁实现  Redisson 框架 set（key，value，NX，ex）
     */
    @RequestMapping("testRedisson")
    public Object testStringSetNxEx() {
        RLock lock = null;
        try {
            Config config = new Config();
            config.useSingleServer().setAddress("redis://47.95.223.193:6382");
            RedissonClient redissonClient = Redisson.create(config);
            lock = redissonClient.getLock("my-lock");
            //上锁
            lock.lock();
            //获取 jedis
            Jedis jedis = jedisPool.getResource();
            //判断如果这个key存在 直接获取  若不存在从数据库获取并放入redis种
            if (jedis.exists("redisson")) {
                return jedis.get("redisson");
            } else {
                jedis.setex("redisson", 30, "分布式锁：redisson");
                return jedis.get("redisson");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != lock)
                //解锁
                lock.unlock();
        }
        return null;
    }

    /**
     * 演示分布式锁实现  set（key，value，NX，ex）
     */
    @RequestMapping("testStringSetNXPX")
    public Object testStringSetNXPX() {
        Jedis jedis = null;
        try {
            //获取 jedis
            jedis = jedisPool.getResource();
            String skuKey = "set:nx:px";
            //获取数据
            String skuJson = jedis.get(skuKey);
            if (null == skuJson) {
                System.out.println("缓存中没有数据");
                //上锁去数据库中查询
                String skuLockKey = "set:nx:px:lock";
                //执行set()
                String lockKey = jedis.set(skuLockKey, "OK", "NX", "PX", 2000);
                //已近上锁
                if ("OK".equals(lockKey)) {
                    System.out.println("获取分布式锁");
                    //从数据库中取得数据
                    //将是数据放入缓存
                    //将对象转换为字符串
                    jedis.setex(skuKey, 30, "set:nx:px分布式锁");
                    return jedis.get(skuKey);
                } else {
                    //其他人等待
                    System.out.println("等待");
                    //等待
                    Thread.sleep(1000);
                    /*
                        自旋
                        一直自旋等待数据获取
                     */
                    return jedis.get(skuKey);
                }
            } else {
                //缓存中有数据
                //将其转换为对象
                return skuJson;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            jedis.close();
        }
        return null;
    }

    /**
     * 演示字符串存储对象
     */
    @RequestMapping("testStringSetJson")
    public Object testStringSetJson() {
        User user = new User();
        user.setId(1);
        user.setName("张三");
        user.setAddress("北京");

        Jedis jedis = jedisPool.getResource();
        jedis.set("user:id", JSON.toJSONString(user));
        return jedis.get("user:id");
    }
}